/*
 * ui_typing.c
 *
 *  Created on: Sep 11, 2013
 *      Author: Ken Arok
 *
 *      Revision history:
 *      ---------------------------------------------------------
 *      Date			|	Revised by		|	Description
 *      ---------------------------------------------------------
 *      1. Sep 11, 2013	|	Yosef			| New establishment
 *
 *
 * \file
 *
 * \brief Common User Interface Typing Library.
 *
 * Copyright (c) 2013 PT Hanindo Automation Solutions. All rights reserved.
 *
 */

#include "timers_hw.h"
#include "key.h"
#include "display.h"
#include "ui_typing.h"

const char AlphaNumericKeyChar[] = "0 +-=<>*/1.,?!()@&2ABCabc3DEFdef4GHIghi5JKLjkl6MNOmno7PQRSpqrs8TUVtuv9WXYZwxyz";

uint8_t vInputKeyAlphaNumeric(uint8_t _row, uint8_t _col, const char _backspace, const char _enter, uint8_t _keyOption, void *_buffer, uint16_t _len)
{
	volatile uint32_t *_keyRateTmr = NULL;
	char _keychar1 = -1, _keychar2 = -1, keyLock = -1;
	uint8_t i, x, y, _exit = 1;
	uint8_t _keyBase = 0, _keyIndex = 0, _keyHeld = 0;
	bool _keyIsValid = false, _keyIsGotten = false;
	char *_ptrBuf, _cDot = '.';

	/* Obtain timer. */
	_keyRateTmr = vTimer10msTake();
	if(_keyRateTmr == NULL) return 1;

	_ptrBuf = (char *)_buffer;
	x = _row;
	y = _col;

	vWaitKeyRelease();

	vSetPositionDisplay(_row, y);
	vControlDisplay(0x0D);

	i = 0;
	do {
		/* Get key. */
		_keychar1 = vGetKeyChar();
		keyLock = _keychar1;

		if(i < _len) {
			_keyIsValid = true;

			switch(_keychar1) {
				case '0': _keyBase = 0; break;
				case '1': _keyBase = 9; break;
				case '2': _keyBase = 18; break;
				case '3': _keyBase = 25; break;
				case '4': _keyBase = 32; break;
				case '5': _keyBase = 39; break;
				case '6': _keyBase = 46; break;
				case '7': _keyBase = 53; break;
				case '8': _keyBase = 62; break;
				case '9': _keyBase = 69; break;

				default:
					if(_keychar1 == _backspace) {

						if(i > 0) {
							i--;
							y--;
						}
						else {
							_exit = 0;
						}

						if(y == 0) {
							x--;
							y = 20;
						}
						_ptrBuf[i] = '\0';

						vPutDisplay(x, y, ' ');
						vSetPositionDisplay(x, y);

						vWaitKeyRelease();
					}
					else if(_keychar1 == _enter) {
						_exit = 0;
					}
					_keyIsValid = false;
				break;
			}
		}
		else {
			_keyIsValid = false;
		}

		if(_keyIsValid == true) {
			/* If key is valid, then process it. */
			if((_keyOption == KEY_TYPING_ALPHA_NUMERIC) || (_keyOption == KEY_TYPING_PASSWORD)) {
				/* Wait until key is defined. */
				_keyIndex = 0;
				_keyHeld = 0;
				_keychar2 = _keychar1;
				_keyIsGotten = false;
				do {

					*_keyRateTmr = 60;

					/* Check if key is gotten. */
					if(_keychar2 == -1) {
						/* Check may be another key is wanted. */
						do {
							_keychar1 = vGetKeyChar();
						}while((_keychar1 == -1) && *_keyRateTmr);
					}

					/* Key is already gotten. */
					if(*_keyRateTmr == 0) {
						_keyIsGotten = true;
					}
					/* Another key is wanted. */
					else if((_keychar1 != keyLock) && (_keychar1 != -1)) {
						_keyIsGotten = true;
					}
					/* User want terminate it. */
					else if((_keychar1 == _enter) || (_keychar1 == _backspace)) {
						_keyIsGotten = true;
					}
					/* Re-define pressed key. */
					else {

						if(_keychar2 == -1) _keyIndex++;

						if(_keyHeld > 2) {
							_keyHeld = 0;
							_keyIndex++;
						}

						switch(_keyBase) {
							case 0:
							case 9:
							case 53:
							case 69:
								if(_keyIndex > 8) _keyIndex = 0;
							break;

							default:
								if(_keyIndex > 6) _keyIndex = 0;
							break;
						}

						if(y <= 20) {
							vPutDisplay(x, y, AlphaNumericKeyChar[_keyBase + _keyIndex]);
						}

						if(y == 20) vSetPositionDisplay(x + 1, 1);

						/* Wait key being released or held. */
						if(_keychar1 == _keychar2) {
							_keyHeld++;
						}

						_keychar2 = _keychar1;
						*_keyRateTmr = 20;
						do {
							_keychar1 = vGetKeyChar();
						}while((_keychar1 != -1) && *_keyRateTmr);
					}

				}while(_keyIsGotten == false);

				if(_keyOption == KEY_TYPING_PASSWORD) {
					vPutDisplay(x, y, '*');
				}

				_ptrBuf[i] = AlphaNumericKeyChar[_keyBase + _keyIndex];

				if(i < (4 * 20 - 1)) {
					i++;
					y++;
				}

				if(y > 20) {
					x++;
					y = 1;
				}
			}
			else {
				if(y <= 20) {
					vPutDisplay(x, y, AlphaNumericKeyChar[_keyBase]);
				}

				if(y == 20) vSetPositionDisplay(x + 1, 1);

				_ptrBuf[i] = AlphaNumericKeyChar[_keyBase];

				if(i < (4 * 20 - 1)) {
					i++;
					y++;
				}

				if(y > 20) {
					x++;
					y = 1;
				}

				if(_keyOption == KEY_TYPING_NUMERIC_TCPIP) {
					if((y == 4) || (y == 8) || (y == 12)) {
						vPutDisplay(x, y, _cDot);
						_ptrBuf[i] = _cDot;
						y++;
						i++;
					}
				}

				vWaitKeyRelease();
			}
		}

	}while(_exit);

	/* Release Timer. */
	vTimer10msGive((void *)_keyRateTmr);

	vControlDisplay(0x0C);
	vWaitKeyRelease();

	if(_keychar1 == _backspace) return 2;
	if(_keychar1 == _enter) {
		if(_ptrBuf[0] == 0) return 3;
	}

	return 0;
}


